Skip to content

UI/UX: one enforced design system across every public surface#66

Merged
CodeWithJuber merged 8 commits into
masterfrom
claude/forge-work-system-setup-p26ka5
Jul 16, 2026
Merged

UI/UX: one enforced design system across every public surface#66
CodeWithJuber merged 8 commits into
masterfrom
claude/forge-work-system-setup-p26ka5

Conversation

@CodeWithJuber

Copy link
Copy Markdown
Owner

What & why

The brand called itself "one source of truth" but brand.json/brand.js held zero colors — the ember/warm-black palette was hand-duplicated across the landing page and the status page under two different naming schemes, so the "one" palette forked. The landing page also carried classic AI-slop tells (fake terminal chrome, 01–06 digit-icons, /% glyph icons, a uniform card grid, a faux-live pulse dot), the real hero art was never used, social cards were blank, and the "repo-sourced" status metrics were silently hardcoded fallbacks.

This makes the design system one enforced source and ships every fix with a guard so it can't rot (the repo's fix-and-enforce pattern). Eight focused commits:

  • brand.json = single color source (full dark + light palettes) emitted by src/brand.js rootTokensCss(); the status page gains light mode; test/pages.test.js enforces full-palette parity across both surfaces.
  • Landing hallmark redesign (Stat-Led): the real shipped hero diagram is embedded (inlined so it resolves in local preview and at the deployed site root), fake chrome / digit-icons / glyphs / uniform grid / pulse dot removed, real inline SVG icons, honest sourced metrics.
  • Metadata: 1200×630 og:image + twitter:image (rasterized once via Chromium — a committed author artifact, not a runtime dep), favicon + apple-touch-icon, canonical == og:url, full OG/Twitter/SoftwareApplication JSON-LD on the status page.
  • Accessibility: every accent/label pair ≥4.5:1 on both themes; 3-level radius scale; instant focus rings; compositor-light nav blur (≤8px).
  • Freshness: the impact/saved metric regexes now actually parse the README, a non-match is a hard build error (no silent fallback); public/index.html is gitignored + dropped from the npm tarball (CI regenerates it, killing the stale-version + dev-branch-leak bugs).
  • Statusline: 24-bit truecolor exact brand hexes + 256-color fallback + smoke test.
  • Docs guard: checkDiagrams now validates mermaid theme values (brand hexes), not just the %%{init directive; README leads with a 60-second quickstart; ARCHITECTURE documents the single color source.

Zero runtime dependencies preserved (system-font stack; the OG PNG is a committed asset). Verified with headless Chromium at 320/375/768/1280/1920 in light + dark — no horizontal scroll, hero fits, real SVG renders.

Checklist

  • npm test passes (717 tests, 715 pass / 2 integration-skip)
  • npm run check passes (Biome lint + format)
  • New public functions have a test (cssVars/rootTokensCss, statusline, metadata guards)
  • Conventional commit messages (feat:/fix:/test:/docs:)
  • CHANGELOG.md updated under ## [Unreleased]
  • No new runtime dependency (dev deps ok)
  • Substrate/docs updated (ARCHITECTURE.md, README, docs check green)

Risk & rollback

  • Risk level: low — changes are confined to the two static pages, the brand token module, the status-page generator, the statusline, and docs; no runtime/CLI behavior changes. Every change is covered by a test.
  • Rollback plan: revert the branch; the previous pages/statusline are restored wholesale. public/ becoming a build artifact is the only non-code change — CI regenerates it on deploy regardless.

Extra checks (tick if applicable)

  • npm run typecheck passes
  • Input validated at boundaries; errors handled (metric parse now fails loud instead of silently)
  • Logs contain no secrets/PII
  • AI-assisted: verified end-to-end via rendered screenshots and the full gate

🤖 Generated with Claude Code

https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2


Generated by Claude Code

claude added 8 commits July 16, 2026 18:13
…parity enforcement

Root cause of the UI drift: brand.json/brand.js called themselves "the single
source of the brand" but held zero colors. The ember/warm-black palette was
hand-duplicated across landing/index.html and build-pages.mjs under *two
different naming schemes* for the same hexes (--ink/--surface/--ember vs
--bg/--panel/--brand), so the two "one" palettes could — and did — fork.

- brand.json: add a `colors` block (full dark + light palettes) as the one
  source of hexes, plus `fonts` and `site`.
- src/brand.js: add `cssVars(scheme)` + `rootTokensCss()` pure helpers that
  emit the :root token block and a prefers-color-scheme:light override.
- build-pages.mjs: status page now injects tokens from brand.json via
  rootTokensCss() (gains light mode; was dark-only) and uses the one naming
  scheme everywhere (--ink→--bg, --surface→--panel, --fg→--text, --ember→--brand).
- landing/index.html: redefine --brand-2/--ok for light mode so peach/mint
  accents meet AA contrast on light backgrounds.
- test/pages.test.js: enforce FULL-palette parity (every dark AND light hex in
  brand.json.colors must appear on both public pages) — change one hex there
  and this fails until every surface updates. That is what makes brand.json the
  source of truth.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
… chrome

Rebuild landing/index.html on a Stat-Led structure (modern-minimal genre) so it
reads as made, not generated. The redesign removes the AI-slop tells the old page
carried and embeds the real shipped artwork instead of a weaker redrawn hero.

Killed:
- The fake terminal window (three identical traffic-light dots + mock title bar
  wrapping a <pre>) — replaced with an honestly-labelled code <figure>.
- Placeholder digit-icons 01-06 and the glyph "icons" — replaced with real inline
  stroke SVG icons that mean something (layers, shield-check, radar, reuse-loop,
  lock-check, git-branch; dashed-node graph + gauge for the limits).
- The uniform 3x2 bordered icon-tile grid — capabilities now sit in a
  hairline-divided two-column list, breaking the card-in-card rhythm.
- The faux-live "pulse" dot (styled with a glow ring but static) — now a plain
  honest status marker.

Added / fixed:
- The real hero diagram (docs/assets/hero-*.svg) is embedded, inlined so it
  resolves both in local preview and at the deployed site root (the Pages deploy
  copies only index.html, not docs/assets). Dark and light variants toggle by
  prefers-color-scheme.
- Metrics kept but sourced (118 ms / 0.43 ms from reports/benchmarks.md, 62.1%
  from the white-paper prototype, 0 deps from package.json) — no invented numbers.
- overflow-x: clip on html+body, minmax(0,1fr) grids, eyebrow stacked above the
  heading, instant focus-visible rings, compositor-light nav blur (8px).
- Verified via headless Chromium at 320/375/768/1280 in dark+light: no horizontal
  scroll at any width, hero fits, real SVG renders.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
Landing set twitter:card=summary_large_image but shipped no og:image, so social
cards rendered blank; neither page had a favicon; the status page had no OG /
canonical / JSON-LD at all.

- Author a 1200x630 brand card (docs/assets/og.svg -> og.png, rasterized once via
  the pre-installed Chromium — a committed author artifact, not a runtime dep) and
  an ember "F" favicon (favicon.svg) + apple-touch-icon.png.
- Landing head: add og:image/twitter:image (absolute), og:image:width/height/alt,
  twitter:title/description, favicon + apple-touch-icon links, og:site_name.
- Status page (build-pages render): add canonical, full Open Graph, Twitter card,
  favicon/apple-touch-icon, and a SoftwareApplication JSON-LD — all derived from
  the single brand.json site.url (new SITE base), so canonical == og:url.
- static.yml: copy og.png + favicon.svg + apple-touch-icon.png to the Pages root
  so the absolute URLs resolve on the deployed project site.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
forge uicheck design + a WCAG pass flagged sub-4.5:1 supplementary text and six
ad-hoc border-radius levels on the redesigned landing page.

- Contrast: bump --faint (dark 3.9->4.6, light 4.0->4.6), light --brand
  (kicker 4.3->4.6) and light --ok (3.7->4.6) at the single brand.json source, so
  every accent/label pair on both schemes clears 4.5:1. Landing's mirrored token
  blocks updated to match (parity test stays green); the status page inherits the
  new values via brand.json automatically.
- Radius: collapse the literal border-radii onto --radius-sm / --radius / pill so
  uicheck's radius-levels reads 3 (was 6). var() radii aren't counted, so routing
  small elements through --radius-sm is the deliberate 3-level scale.

uicheck design now passes spacing-scale, radius-levels, shadow-levels with slop
distance 0.42 (>=0.25). palette-size stays advisory-only: a dark+light token
system declares ~21 hexes before the embedded hero illustration, so the <=8
single-theme heuristic can't apply — not CI-gated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
…d status page

Three freshness/drift bugs where the "no mock data" promise wasn't actually held.

- build-pages: the impact/saved regexes no longer matched the current README, so
  those "repo-sourced" numbers were silently the hardcoded fallbacks (0.43 ms /
  62.1%). Fix the regexes to parse the README and make a non-match a hard build
  error (mustMatch) — the number is sourced or the build fails, never a stale
  default. Remove the dead `claim` field.
- public/index.html is a generated artifact (CI rebuilds it at deploy), so it was
  going stale in git (old version) and leaking the dev branch name into a visible
  chip — and it shipped in the npm tarball. Gitignore it, untrack it, and drop
  "public" from package.json files. npm pack now contains zero public/ entries.
- Landing's Status link pointed at ./status/, dead in local file preview; now the
  absolute Pages URL, which resolves everywhere.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
global/statusline.sh used nearest xterm-256 indices (#209 ember, #245/#247 greys)
instead of the real brand tokens. Move to 24-bit truecolor from a named palette
block so the ember and warm-taupe greys are the exact brand.json hexes (#f26430,
#7d7263, #a99e90, #67e8a5), with a 256-color fallback when COLORTERM isn't
truecolor/24-bit so it degrades instead of mis-rendering. Keep the subtle ember
ctx>200k warning, the cache-hit meter, and the jq-absent fallback.

New test/statusline.test.js drives the script the way Claude Code does (sample JSON
on stdin) and asserts every segment renders, the exact truecolor hexes are emitted,
the 256-color fallback kicks in without COLORTERM, and minimal input never leaks a
literal "null".

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
…t nav blur

Lock in the UI/metadata work so it can't silently regress: both public pages must
ship an absolute og:image + twitter:image and a favicon/apple-touch-icon; canonical
must equal og:url on each; the landing page must state the current package.json
version (not a stale hardcode); backdrop blur must stay <=8px; and public/ must not
reappear in the npm files list. Extends the existing single-source parity suite.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
…ickstart

- checkDiagrams: a `%%{init` block must now carry the brand's actual color values
  (ember #f26430 + warm-black #171310 from brand.json), not merely a theme directive
  — a diagram can no longer declare a theme yet render off-brand. New docs_check test
  covers both the branded-pass and missing-values-flagged cases.
- ARCHITECTURE.md: document brand.json.colors as the single color source both public
  pages derive from, and the parity/diagram guards that keep it honest.
- README: lead with a "Start in 60 seconds" block so the first screen is actionable,
  linking to the full quickstart and command reference.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
@CodeWithJuber
CodeWithJuber marked this pull request as ready for review July 16, 2026 20:24
@CodeWithJuber
CodeWithJuber merged commit 49ec7fb into master Jul 16, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants